package com.neusoft.hifly.information.column.service.impl;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import com.neusoft.hifly.commons.exception.SystemErrorException;
import com.neusoft.hifly.commons.lang.LongUtil;
import com.neusoft.hifly.commons.lang.StringConstants;
import com.neusoft.hifly.core.basic.domain.ZTreeNode;
import com.neusoft.hifly.core.basic.service.impl.CTSaaSBaseServiceImpl;
import com.neusoft.hifly.core.log.annotation.LogType;
import com.neusoft.hifly.core.log.annotation.OperationLog;
import com.neusoft.hifly.core.token.TokenContextHolder;
import com.neusoft.hifly.core.utils.GlobalConstants;
import com.neusoft.hifly.dynamicds.multi.annotation.MultiDynamicRoutingDataSource;
import com.neusoft.hifly.information.article.dao.IArtToColDao;
import com.neusoft.hifly.information.column.dao.IColumnDao;
import com.neusoft.hifly.information.column.entity.ColumnObj;
import com.neusoft.hifly.information.column.service.IColumnService;
import com.neusoft.hifly.information.power.dao.IColumnPowerDao;

/**
 * Title: 文章资讯服务
 * <p>
 * Description: 栏目 Service
 * <p>
 * Copyright: 2019
 * <p>
 * Company: 东软汉枫
 *
 * @author lh_neu
 * @version 1.0.0
 */
@Service
@MultiDynamicRoutingDataSource
public class ColumnServiceImpl extends CTSaaSBaseServiceImpl implements IColumnService {
	@Autowired(required = false)
	private IColumnDao columnDao;
	@Autowired(required = false)
	private IColumnPowerDao columnPowerDao;
	@Autowired(required = false)
	private IArtToColDao artToColDao;

	/**
	 * 保存对象
	 *
	 * @param organCode
	 *            租户编码
	 * @param organLogicId
	 *            租户逻辑ID
	 * @param obj
	 *            对象
	 * @throws SystemErrorException
	 *             自定义异常
	 */
	@Override
	@OperationLog(method = LogType.UPDATE, msg = "栏目")
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = { Exception.class, RuntimeException.class })
	public void saveOrUpdate(final String organCode, final long organLogicId, final ColumnObj obj)
			throws SystemErrorException {
		if (StringUtils.isEmpty(organCode) || obj == null) {
			return;
		}
		if (StringUtils.isEmpty(obj.getOrganCode())) {
			obj.setOrganCode(organCode);
		}
		if (LongUtil.isEmpty(obj.getOrganLogicId())) {
			obj.setOrganLogicId(organLogicId);
		}

		final String name = StringUtils.trimToEmpty(obj.getName());
		if (StringUtils.isEmpty(name)) {
			throw new SystemErrorException("名称不能为空!");
		}

		final ColumnObj oldObj = columnDao.getByLogicId(organCode, organLogicId, obj.getLogicId());

		obj.setOrganLogicId(organLogicId);

		// 有ID的话要判断是否保存还是更新
		if (oldObj == null) {
			// 保存

			obj.setId(idWorker.nextId());
			if (LongUtil.isEmpty(obj.getLogicId())) {
				obj.setLogicId(idWorker.nextId());
			}
			obj.setUpdateTime(LocalDateTime.now());

			if (StringUtils.isEmpty(obj.getUpdatePerson())) {
				obj.setUpdatePerson(TokenContextHolder.get().getUserName());
			}

			this.setForm(obj, obj);

			/* 更新栏目ID串 */
			this.updateIdPath(organCode, organLogicId, obj);

			columnDao.insert(obj);

		} else {
			// 更新

			this.setForm(obj, oldObj);

			oldObj.setUpdateTime(LocalDateTime.now());
			if (StringUtils.isEmpty(oldObj.getUpdatePerson())) {
				oldObj.setUpdatePerson(TokenContextHolder.get().getUserName());
			}

			/* 更新栏目ID串 */
			this.updateIdPath(organCode, organLogicId, oldObj);

			columnDao.updateById(oldObj);

		}
	}

	/**
	 * 根据ID删除对象
	 *
	 * @param organCode
	 *            租户编码
	 * @param organLogicId
	 *            租户逻辑ID
	 * @param logicId
	 *            对象ID
	 */
	@Override
	@OperationLog(method = LogType.DELETE, msg = "栏目")
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = { Exception.class, RuntimeException.class })
	public void deleteByLogicId(final String organCode, final long organLogicId, final long logicId) {
		if (StringUtils.isEmpty(organCode)) {
			return;
		}

		columnDao.deleteByLogicId(organCode, organLogicId, logicId);

		columnPowerDao.deleteByColumnLogicId(organCode, organLogicId, logicId);

		artToColDao.deleteByColumnLogicId(organCode, organLogicId, logicId);
	}

	/**
	 * 批量删除对象
	 *
	 * @param organCode
	 *            租户编码
	 * @param organLogicId
	 *            租户逻辑ID
	 * @param logicIds
	 *            对象ID，多id使用英文逗号分隔
	 */
	@Override
	public void deleteByBatch(final String organCode, final long organLogicId, final String logicIds) {
		if (StringUtils.isEmpty(organCode) || StringUtils.isEmpty(logicIds)) {
			return;
		}
		final String[] logicIdArr = logicIds.split(StringConstants.STRING_SPLIT_FLAG_3);
		if (logicIdArr == null) {
			return;
		}
		for (final String logicId : logicIdArr) {
			if (StringUtils.isEmpty(logicId)) {
				continue;
			}
			this.deleteByLogicId(organCode, organLogicId, Long.parseLong(logicId));
		}
	}

	/**
	 * 根据id查询对象
	 *
	 * @param organCode
	 *            租户编码
	 * @param organLogicId
	 *            租户逻辑ID
	 * @param logicId
	 *            对象logicId
	 * @return 对象
	 */
	@Override
	public ColumnObj getByLogicId(final String organCode, final long organLogicId, final long logicId) {
		if (StringUtils.isEmpty(organCode)) {
			return null;
		}
		return columnDao.getByLogicId(organCode, organLogicId, logicId);
	}

	/**
	 * 根据id查询对象
	 * <p>
	 * 判断是否有权限
	 *
	 * @param organCode
	 *            租户编码
	 * @param organLogicId
	 *            租户逻辑ID
	 * @param logicId
	 *            对象logicId
	 * @param isPower
	 *            是否根据权限查询
	 * @param userLogicId
	 *            当前查询栏目的用户ID
	 * @return 对象
	 */
	@Override
	public ColumnObj getByLogicId(final String organCode, final long organLogicId, final long logicId,
			final boolean isPower, final long userLogicId) {
		if (StringUtils.isEmpty(organCode)) {
			return null;
		}

		final ColumnObj column = columnDao.getByLogicId(organCode, organLogicId, logicId);
		if (column == null) {
			return null;
		}
		if (isPower && GlobalConstants.ABS_ID != userLogicId) {
			// 只查询有权限的栏目
			List<ColumnObj> list = new ArrayList<ColumnObj>(1);
			list.add(column);
			list = checkPower(organLogicId, organCode, userLogicId, list);
			if (list != null && !list.isEmpty()) {
				return list.get(0);
			} else {
				return null;
			}
		} else {
			return column;
		}
	}

	/**
	 * 查询所有对象
	 *
	 * @param organCode
	 *            租户编码
	 * @param organLogicId
	 *            租户逻辑ID
	 * @return 对象集合
	 */
	@Override
	public List<ColumnObj> findAll(final String organCode, final long organLogicId) {
		if (StringUtils.isEmpty(organCode)) {
			return null;
		}
		return columnDao.findAll(organCode, organLogicId);
	}

	/**
	 * 查询所有对象
	 *
	 * @param organCode
	 *            租户编码
	 * @param organLogicId
	 *            租户逻辑ID
	 * @param isPower
	 *            是否根据权限查询
	 * @param userLogicId
	 *            当前查询栏目的用户ID
	 * @return 对象集合
	 */
	@Override
	public List<ColumnObj> findAll(final String organCode, final long organLogicId, final boolean isPower,
			final long userLogicId) {
		if (StringUtils.isEmpty(organCode)) {
			return null;
		}

		final List<ColumnObj> list = columnDao.findAll(organCode, organLogicId);
		if (isPower && GlobalConstants.ABS_ID != userLogicId) {
			// 只查询有权限的栏目
			return checkPower(organLogicId, organCode, userLogicId, list);
		} else {
			return list;
		}
	}

	/**
	 * 查询下级子栏目
	 *
	 * @param organCode
	 *            租户编码
	 * @param organLogicId
	 *            租户逻辑ID
	 * @param pid
	 *            父ID
	 * @param isPower
	 *            是否根据权限查询
	 * @param userLogicId
	 *            当前查询栏目的用户ID
	 * @return 对象集合
	 */
	@Override
	public List<ColumnObj> findByPid(final String organCode, final long organLogicId, final long pid,
			final boolean isPower, final long userLogicId) {
		if (StringUtils.isEmpty(organCode)) {
			return null;
		}

		final List<ColumnObj> list = columnDao.findByPid(organCode, organLogicId, pid);
		if (isPower && GlobalConstants.ABS_ID != userLogicId) {
			// 只查询有权限的栏目
			return checkPower(organLogicId, organCode, userLogicId, list);
		} else {
			return list;
		}
	}

	/**
	 * 查询所有下级子栏目，包括自己和所有子的子
	 *
	 * @param organCode
	 *            租户编码
	 * @param organLogicId
	 *            租户逻辑ID
	 * @param pid
	 *            父ID
	 * @param isPower
	 *            是否根据权限查询
	 * @param userLogicId
	 *            当前查询栏目的用户ID
	 * @return 对象集合
	 */
	@Override
	public List<ColumnObj> findAllSubsByPid(final String organCode, final long organLogicId, final long pid,
			final boolean isPower, final long userLogicId) {
		if (StringUtils.isEmpty(organCode)) {
			return null;
		}
		final List<ColumnObj> result = new ArrayList<ColumnObj>(0);

		final ColumnObj father = columnDao.getByLogicId(organCode, organLogicId, pid);
		if (father == null) {
			return null;
		}
		// 当前栏目
		result.add(father);
		// 子栏目
		final List<ColumnObj> subs = columnDao.findAllNotRootSubsByIdPath(organCode, organLogicId, father.getIdPath());
		if (subs != null && !subs.isEmpty()) {
			result.addAll(subs);
		}

		if (isPower && GlobalConstants.ABS_ID != userLogicId) {
			// 只查询有权限的栏目
			return checkPower(organLogicId, organCode, userLogicId, result);
		} else {
			return result;
		}
	}

	/**
	 * 根据条件查询
	 *
	 * @param organCode
	 *            租户编码
	 * @param organLogicId
	 *            租户逻辑ID
	 * @param property
	 *            参数。其中isLike:Boolean 是否模糊查询
	 * @return 集合
	 */
	@Override
	public List<ColumnObj> search(final String organCode, final long organLogicId, Map<String, Object> property) {
		if (StringUtils.isEmpty(organCode)) {
			return null;
		}
		if (property == null) {
			property = new HashMap<String, Object>(1);
			property.put("organLogicId", organLogicId);
		}
		final QueryWrapper<ColumnObj> queryWrapper = new QueryWrapper<ColumnObj>();
		replaceProperty(property);
		createSql(property, queryWrapper, new String[] { "COLUMN_ORDER", "UPDATE_TIME" });
		return columnDao.selectList(queryWrapper);
	}

	/**
	 * 根据条件查询
	 *
	 * @param organCode
	 *            租户编码
	 * @param organLogicId
	 *            租户逻辑ID
	 * @param offset
	 *            当前页数
	 * @param limit
	 *            分页长度
	 * @param property
	 *            参数。其中isLike:Boolean 是否模糊查询
	 * @return 返回Map
	 */
	@Override
	public IPage<ColumnObj> search(final String organCode, final long organLogicId, final int offset, final int limit,
			Map<String, Object> property) {
		if (StringUtils.isEmpty(organCode)) {
			return null;
		}
		if (property == null) {
			property = new HashMap<String, Object>(1);
			property.put("organLogicId", organLogicId);
		}
		final IPage<ColumnObj> page = new Page<ColumnObj>(offset, limit);
		final QueryWrapper<ColumnObj> queryWrapper = new QueryWrapper<ColumnObj>();
		replaceProperty(property);
		createSql(property, queryWrapper, new String[] { "COLUMN_ORDER", "UPDATE_TIME" });
		return columnDao.selectPage(page, queryWrapper);
	}

	/**
	 * 栏目树节点
	 *
	 * @param organCode
	 *            租户编码
	 * @param organLogicId
	 *            租户ID
	 * @param userLogicId
	 *            当前用户ID
	 * @return 节点
	 */
	@Override
	public List<ZTreeNode> findNodes(final String organCode, final long organLogicId, final long userLogicId) {
		return subNodes(organCode, organLogicId, userLogicId, GlobalConstants.ABS_ID);
	}

	/**
	 * 获取子节点
	 *
	 * @param organCode
	 *            租户编码
	 * @param organLogicId
	 *            租户ID
	 * @param userLogicId
	 *            当前用户ID
	 * @param pid
	 *            父ID
	 * @return 节点
	 */
	private List<ZTreeNode> subNodes(final String organCode, final long organLogicId, final long userLogicId,
			final long pid) {
		final List<ZTreeNode> nodeList = new ArrayList<ZTreeNode>(0);
		final List<ColumnObj> subs = findByPid(organCode, organLogicId, pid, false, userLogicId);
		if (subs != null && !subs.isEmpty()) {
			ZTreeNode node = null;
			List<ZTreeNode> subNodes = null;
			for (final ColumnObj table : subs) {
				node = new ZTreeNode("column", table.getName()).logicId(table.getLogicId()).name(table.getName())
						.fatherLogicId(table.getPid());

				subNodes = subNodes(organCode, organLogicId, userLogicId, table.getLogicId());
				if (subNodes != null && !subNodes.isEmpty()) {
					node.children(subNodes);
				} else {
					node.leaf();
				}

				nodeList.add(node);
			}
		}
		return nodeList;
	}

	/**
	 * 更新栏目ID串
	 *
	 * @param organCode
	 *            租户编码
	 * @param organLogicId
	 *            租户逻辑ID
	 * @param obj
	 *            当前栏目
	 */
	private void updateIdPath(final String organCode, final long organLogicId, final ColumnObj obj) {

		final String oldIdPath = obj.getIdPath();

		final StringBuffer idPath = new StringBuffer();

		if (GlobalConstants.ABS_ID != obj.getPid()) {
			final ColumnObj fatherCol = this.getByLogicId(organCode, organLogicId, obj.getPid());
			if (fatherCol != null) {
				if (StringUtils.isEmpty(fatherCol.getIdPath())) {
					idPath.append(fatherCol.getLogicId() + StringConstants.STRING_SPLIT_FLAG_3);
				} else {
					idPath.append(fatherCol.getIdPath());
				}
				obj.setRootId(fatherCol.getRootId());
			} else {
				obj.setRootId(obj.getLogicId());
				obj.setPid(GlobalConstants.ABS_ID);
				idPath.append(StringConstants.STRING_SPLIT_FLAG_3);
			}
		} else {
			obj.setRootId(obj.getLogicId());
			obj.setPid(GlobalConstants.ABS_ID);
			idPath.append(StringConstants.STRING_SPLIT_FLAG_3);
		}

		idPath.append(obj.getLogicId());
		idPath.append(StringConstants.STRING_SPLIT_FLAG_3);
		obj.setIdPath(idPath.toString());

		// 修改孩子
		final List<ColumnObj> subCols = this.columnDao.findAllNotRootSubsByIdPath(organCode, organLogicId, oldIdPath);
		for (final ColumnObj subCol : subCols) {
			subCol.setIdPath(StringUtils.replace(subCol.getIdPath(), oldIdPath, obj.getIdPath()));

			// 依据该策略重置子栏目策略
			if (StringConstants.YES.equals(obj.getIsResetSub())) {
				subCol.setSyncMiniSite(obj.getSyncMiniSite());
				subCol.setSyncApp(obj.getSyncApp());
				subCol.setCommentRule(obj.getCommentRule());
				subCol.setApproveRule(obj.getApproveRule());
				subCol.setColumnRule(obj.getColumnRule());
			}

			this.columnDao.updateById(subCol);
		}
	}

	/**
	 * 过滤无权限的栏目
	 *
	 * @param organLogicId
	 *            租户逻辑ID
	 * @param organCode
	 *            租户编码
	 * @param userLogicId
	 *            当前查询栏目的用户ID
	 * @param list
	 *            栏目集合
	 * @return 只保留有权限的栏目
	 */
	private List<ColumnObj> checkPower(final long organLogicId, final String organCode, final long userLogicId,
			final List<ColumnObj> list) {

		return list;
		// TODO 【待开发】栏目权限
		//		if (StringUtils.isEmpty(userLogicId) || list == null || list.isEmpty()) {
		//			return null;
		//		}
		//
		//		final List<OrgObj> nowOrgs = upOrgDao.findByUserLogicId(organLogicId, userLogicId);
		//		final List<PositionObj> nowPositions = positionDao.findByUserLogicId(organLogicId, userLogicId);
		//
		//		final List<ColumnObj> results = new ArrayList<ColumnObj>(0);
		//		List<ColumnPowerObj> powers = null;
		//		for (final ColumnObj obj : list) {
		//			/* 只处理需要授权的 */
		//
		//			// 查询栏目权限
		//			powers = columnPowerDao.findByColumnLogicId(organCode, obj.getLogicId());
		//			if (powers == null) {
		//				continue;
		//			}
		//			for (final ColumnPowerObj power : powers) {
		//				if (TreeStatus.ITEM_ORG.equalsIgnoreCase(power.getObjType())) {
		//					if (nowOrgs == null || nowOrgs.isEmpty()) {
		//						continue;
		//					}
		//					for (final OrgObj oObj : nowOrgs) {
		//						// 判断：当前级可见
		//						if (oObj.getLogicId().equals(power.getObjId())) {
		//							results.add(obj);
		//							break;
		//						}
		//
		//					}
		//
		//				} else if (TreeStatus.ITEM_POSITION.equalsIgnoreCase(power.getObjType())) {
		//					if (nowPositions == null || nowPositions.isEmpty()) {
		//						continue;
		//					}
		//
		//					for (final PositionObj pObj : nowPositions) {
		//						// 判断：当前级可见
		//						if (pObj.getLogicId().equals(power.getObjId())) {
		//							results.add(obj);
		//							break;
		//						}
		//					}
		//
		//				} else if (TreeStatus.ITEM_USER.equalsIgnoreCase(power.getObjType())) {
		//					// 判断：当前级可见
		//					if (userLogicId.equals(power.getObjId())) {
		//						results.add(obj);
		//						continue;
		//					}
		//				}
		//			}
		//		}
		//
		//		// 去除重复数据
		//		StringUtil.removeListDuplicate(results);
		//		// 集合排序——降序
		//		Collections.sort(results, Collections.reverseOrder());
		//		return results;
	}

	/**
	 * 复制信息
	 *
	 * @param fromObj
	 *            原信息
	 * @param toObj
	 *            新信息
	 */
	private void setForm(final ColumnObj fromObj, final ColumnObj toObj) {
		toObj.setOrganLogicId(fromObj.getOrganLogicId());
		toObj.setPid(fromObj.getPid());
		toObj.setName(StringUtils.trimToEmpty(fromObj.getName()));
		toObj.setImg(StringUtils.trimToEmpty(fromObj.getImg()));
		toObj.setMyOrder(fromObj.getMyOrder());
		toObj.setArtTemplate(StringUtils.trimToEmpty(fromObj.getArtTemplate()));
		toObj.setSyncMiniSite(StringUtils.trimToEmpty(fromObj.getSyncMiniSite()));
		toObj.setSyncApp(StringUtils.trimToEmpty(fromObj.getSyncApp()));
		toObj.setCommentRule(StringUtils.trimToEmpty(fromObj.getCommentRule()));
		toObj.setApproveRule(StringUtils.trimToEmpty(fromObj.getApproveRule()));
		toObj.setColumnRule(StringUtils.trimToEmpty(fromObj.getColumnRule()));
		toObj.setMemo(StringUtils.trimToEmpty(fromObj.getMemo()));
		toObj.setExt1(StringUtils.trimToEmpty(fromObj.getExt1()));
		toObj.setExt2(StringUtils.trimToEmpty(fromObj.getExt2()));
		toObj.setExt3(StringUtils.trimToEmpty(fromObj.getExt3()));
		toObj.setExt4(StringUtils.trimToEmpty(fromObj.getExt4()));
		toObj.setExt5(StringUtils.trimToEmpty(fromObj.getExt5()));

	}

	/**
	 * 将对象属性替换成数据库列
	 *
	 * @param property
	 *            参数
	 */
	private void replaceProperty(final Map<String, Object> property) {
		if (property != null) {
			if (property.containsKey("organLogicId")) {
				property.put("ORGAN_LOGIC_ID", property.get("organLogicId"));
				property.remove("organLogicId");
			}
			if (property.containsKey("pid")) {
				property.put("COLUMN_PID", property.get("pid"));
				property.remove("pid");
			}
			if (property.containsKey("rootId")) {
				property.put("COLUMN_ROOTID", property.get("rootId"));
				property.remove("rootId");
			}
			if (property.containsKey("idPath")) {
				property.put("COLUMN_ID_PATH", property.get("idPath"));
				property.remove("idPath");
			}
			if (property.containsKey("name")) {
				property.put("COLUMN_NAME", property.get("name"));
				property.remove("name");
			}
			if (property.containsKey("img")) {
				property.put("COLUMN_IMG", property.get("img"));
				property.remove("img");
			}
			if (property.containsKey("myOrder")) {
				property.put("COLUMN_ORDER", property.get("myOrder"));
				property.remove("myOrder");
			}
			if (property.containsKey("artTemplate")) {
				property.put("ART_TEMPLATE", property.get("artTemplate"));
				property.remove("artTemplate");
			}
			if (property.containsKey("syncMiniSite")) {
				property.put("SYNC_MINI_SITE", property.get("syncMiniSite"));
				property.remove("syncMiniSite");
			}
			if (property.containsKey("syncApp")) {
				property.put("SYNC_APP", property.get("syncApp"));
				property.remove("syncApp");
			}
			if (property.containsKey("commentRule")) {
				property.put("COMMENT_RULE", property.get("commentRule"));
				property.remove("commentRule");
			}
			if (property.containsKey("approveRule")) {
				property.put("APPROVE_RULE", property.get("approveRule"));
				property.remove("approveRule");
			}
			if (property.containsKey("columnRule")) {
				property.put("COLUMN_RULE", property.get("columnRule"));
				property.remove("columnRule");
			}
			if (property.containsKey("memo")) {
				property.put("COLUMN_MEMO", property.get("memo"));
				property.remove("memo");
			}
			if (property.containsKey("updatePerson")) {
				property.put("UPDATE_PERSON", property.get("updatePerson"));
				property.remove("updatePerson");
			}
			if (property.containsKey("updateTime")) {
				property.put("UPDATE_TIME", property.get("updateTime"));
				property.remove("updateTime");
			}
			if (property.containsKey("ext1")) {
				property.put("EXT1", property.get("ext1"));
				property.remove("ext1");
			}
			if (property.containsKey("ext2")) {
				property.put("EXT2", property.get("ext2"));
				property.remove("ext2");
			}
			if (property.containsKey("ext3")) {
				property.put("EXT3", property.get("ext3"));
				property.remove("ext3");
			}
			if (property.containsKey("ext4")) {
				property.put("EXT4", property.get("ext4"));
				property.remove("ext4");
			}
			if (property.containsKey("ext5")) {
				property.put("EXT5", property.get("ext5"));
				property.remove("ext5");
			}

		}
	}
}